<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class Captcha
{

    private $_charNum = 6;
    private $_font;
    private $_fontColor = array(0, 0, 0);
    private $_background = false;
    private $_width = 300;
    private $_height = 100;
    private $_wave = array();

    public function __construct(array $config = array())
    {
// Efecto ondas
        $this->_wave['periodoX'] = 30;
        $this->_wave['amplitudX'] = 10;
        $this->_wave['periodoY'] = 20;
        $this->_wave['amplitudY'] = 10;

        $this->_font[] = array(
            'fuente' => 'arialbd.ttf',
            'separacion' => 5,
            'sizeMin' => 50,
            'sizeMax' => 80,
            'anguloMin' => -10,
            'anguloMax' => 10,
            'posicionX' => 80,
            'posicionY' => 120,
        );

        if (count($config) > 0) {
            foreach ($config as $key => $val) {
                $this->{'_' . $key} = $val;
            }
        }

//duplicamos el ancho y alto, despues se redimensiona al original(genera imagenes mas suaves)
        $this->_width *= 2;
        $this->_height *= 2;
    }

    public function addFont($font, $multiple = false)
    {
        if (!$multiple) {
            if (!is_array($font)) {
                $defaultFont = $this->_font[0];
                $defaultFont['fuente'] = $font;
                $this->_font[] = $defaultFont;
            } else {
                $this->_font[] = array(
                    'fuente' => $font[0],
                    'separacion' => $font[1],
                    'sizeMin' => $font[2],
                    'sizeMax' => $font[3],
                    'anguloMin' => $font[4],
                    'anguloMax' => $font[5],
                    'posicionX' => $font[6],
                    'posicionY' => $font[7],
                );
            }
        } else {
            foreach ($font as $f) {
                $this->_font[] = array(
                    'fuente' => $f[0],
                    'separacion' => $f[1],
                    'sizeMin' => $f[2],
                    'sizeMax' => $f[3],
                    'anguloMin' => $f[4],
                    'anguloMax' => $f[5],
                    'posicionX' => $f[6],
                    'posicionY' => $f[7],
                );
            }
        }
    }

    public function addFontColor($fontColor)
    {
        $this->_fontColor = $fontColor[mt_rand(0, count($fontColor) - 1)];
    }

    public function addBackground($background)
    {
        $this->_background = $background[mt_rand(0, count($background) - 1)];
    }

    public function createCaptcha($texto)
    {
        //$texto = $this->_randomText($this->_charNum);

        $imagenTexto = $this->_createTextImage($texto);

        if ($this->_wave !== false) {
            $this->_waveEffect($imagenTexto);
        }

        $this->_resizeAndPrint($imagenTexto);

        return $texto;
    }

    private function _createTextImage($texto)
    {
        $imagen = imagecreatetruecolor($this->_width, $this->_height);
        imagealphablending($imagen, false);
        $backColor = imagecolorallocatealpha($imagen, 0, 0, 0, 127);
        imagefilledrectangle($imagen, 0, 0, $this->_width, $this->_height, $backColor);
        $fontColor = imagecolorallocate($imagen, $this->_fontColor[0], $this->_fontColor[1], $this->_fontColor[2]);
        imagealphablending($imagen, true);

        $fontRand = mt_rand(0, count($this->_font) - 1);
        for ($i = 0; $i < strlen($texto); $i++) {
            $site = imagettftext($imagen,
                            mt_rand($this->_font[$fontRand]['sizeMin'],
                                    $this->_font[$fontRand]['sizeMax']),
                            mt_rand($this->_font[$fontRand]['anguloMin'],
                                    $this->_font[$fontRand]['anguloMax']),
                            $this->_font[$fontRand]['posicionX'],
                            $this->_font[$fontRand]['posicionY'],
                            $fontColor,
                            __DIR__ . '\fonts\\' . $this->_font[$fontRand]['fuente'], substr($texto, $i, 1)
            );

            $this->_font[$fontRand]['posicionX'] += $site[2] -
                    $this->_font[$fontRand]['posicionX'] +
                    $this->_font[$fontRand]['separacion'];
        }

        imagealphablending($imagen, false);

        return $imagen;
    }

    private function _waveEffect($imagen)
    {
// Wave X
        $rand = mt_rand(0, 100);
        for ($i = 0; $i < ($this->_width); $i += 2) {
            imagecopy($imagen, $imagen,
                    $i - 2, sin($rand + $i / $this->_wave['periodoX']) * $this->_wave['amplitudX'],
                    $i, 0,
                    2, ($this->_height));
        }

// Wave Y
        $rand = mt_rand(0, 100);
        for ($i = 0; $i < ($this->_height); $i += 2) {
            imagecopy($imagen, $imagen,
                    sin($rand + $i / $this->_wave['periodoY']) * $this->_wave['amplitudY'], $i - 2,
                    0, $i,
                    ($this->_width), 2);
        }
    }

    private function _resizeAndPrint($imagen)
    {
        if (is_array($this->_background)) {
            $finalImage = imagecreatetruecolor($this->_width / 2, $this->_height / 2);
            $bgColor = imagecolorallocate($finalImage, $this->_background[0], $this->_background[1], $this->_background[2]);
            imagefilledrectangle($finalImage, 0, 0, $this->_width / 2, $this->_height / 2, $bgColor);
            imagecopyresampled($finalImage, $imagen, 0, 0, 0, 0, $this->_width / 2, $this->_height / 2, $this->_width, $this->_height);
            imagedestroy($imagen);
        } elseif (is_string($this->_background)) {
            $finalImage = imagecreatefrompng(__DIR__ . '\backgrounds\\' . $this->_background);
            imagecopyresampled($finalImage, $imagen, 0, 0, 0, 0, $this->_width / 2, $this->_height / 2, $this->_width, $this->_height);
            imagedestroy($imagen);
        } else {
            $finalImage = imagecreatetruecolor($this->_width / 2, $this->_height / 2);
            imagealphablending($finalImage, false);
            imagesavealpha($finalImage, true);
            $transparent = imagecolorallocatealpha($finalImage, 255, 255, 255, 127);
            imagefilledrectangle($finalImage, 0, 0, $this->_width / 2, $this->_height / 2, $transparent);
            imagecopyresampled($finalImage, $imagen, 0, 0, 0, 0, $this->_width / 2, $this->_height / 2, $this->_width, $this->_height);
            imagedestroy($imagen);
        }

        header("Content-type: image/png");
        imagepng($finalImage);
        imagedestroy($finalImage);
    }

    public function randomText($charNum)
    {
        $text = '';
        $chars = "abcdefghijklmnopqrstuvwxyz";

        for ($i = 0; $i < $charNum; $i++) {
            $text .= $chars[mt_rand(0, 25)];
        }

        return $text;
    }

}